package be.ipl.streams.usecases;

import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.ejb.Remote;

import be.ipl.streams.domaine.Game;
import be.ipl.streams.domaine.Grid;
import be.ipl.streams.domaine.Player;
import be.ipl.streams.exceptions.ArgumentInvalideException;
import be.ipl.streams.exceptions.GameOverException;
import be.ipl.streams.exceptions.GameStartedException;
import be.ipl.streams.exceptions.NoPlayersException;
import be.ipl.streams.exceptions.RoundExpiredException;

@Remote
public interface GameManagement {
	
	/**
	 * Create a game that will start as a lobby
	 * @param name 
	 * 			Name of the game
	 * @param creator 
	 * 			The creator
	 * @return 
	 * 			The created game
	 * @throws ArgumentInvalideException
	 */
	Game createGame(String name, Player creator)
            throws ArgumentInvalideException;
	
	/**
	 * Return a game base on an id
	 * @param id
	 * @return
	 * @throws ArgumentInvalideException
	 */
	Game getGame(int id) throws ArgumentInvalideException;
	
	/**
	 * Join a game in lobby state
	 * @param game 
	 * 			The game to be joined
	 * @return 
	 * 			The game joined
	 * @throws GameStartedException 
	 * 			If game already started
	 * @throws ArgumentInvalideException 
	 */
    Game join(int id, Player player) 
    		throws GameStartedException, ArgumentInvalideException ;
	
	/**
	 * Play the next round
	 * @param game
	 * @return The new token
	 * @throws GameOverException
	 * 			If game is not playing
	 * @throws NoPlayersException
	 * 			If no enough player to start a game 
	 * @throws ArgumentInvalideException 
	 * 			If given game isn't a correct object
	 */
	Game nextTurn(Game game) 
			throws GameOverException, NoPlayersException, ArgumentInvalideException;
	
	/**
     * The move of the player for the current turn
     * @param game
     * @param player
     * @param position 
     * 			The position on the grid where the player put the actual token
     * @return 
     * @throws RoundExpiredException 
     * 			If player's answer arrive to late, after the round ended
	 * @throws ArgumentInvalideException 
     */
    Game playRound(Game game, Player player, int turn, int position)
    		throws RoundExpiredException, ArgumentInvalideException;
	
	/**
	 * Return the token of the current turn
	 * @param game
	 * @return
	 * @throws ArgumentInvalideException 
	 */
	int getCurrentToken(Game game) throws ArgumentInvalideException;
    
	/**
	 * Give a set of player who didn't play at the given turn
	 * @return
	 * @throws ArgumentInvalideException 
	 * @throws GameOverException 
	 * @throws GameStartedException 
	 */
    Set<Player> getInactivePlayers(Game game) throws ArgumentInvalideException, GameStartedException, GameOverException;
    
    /**
     * List all game in lobby state
     * @return 
     * 			The games
     */
    List<Game> listLobbys();
    
   /**
    * List all games
    * @return A list of games
    */
    List<Game> listAllGames();
    
    /**
     * Get the players in a game
     * @param game
     * @return
     */
    Set<Player> listPlayers(Game game);

    /**
     * Show the log of a game
     * @param id
     * @return
     */
    String checkGameLog(int id);
    
    /**
     * 
     * @param game
     * @param player
     * @return
     * @throws ArgumentInvalideException 
     */
    Grid displayGrid(Game game, Player player) throws ArgumentInvalideException;
    
    /**
     * Get the played token in order
     * @param grid
     * @return
     * @throws ArgumentInvalideException 
     */
    List<Integer> getPositions(Grid grid) throws ArgumentInvalideException;
    
    /**
     * 
     * @param game
     * @return
     * 		return the score of all grid of the specified game
     * @throws ArgumentInvalideException 
     */
    Map<Player, Integer> getScores(Game game) throws ArgumentInvalideException;

    
	/**
	 * @param game
	 * @param grid
	 * @return
	 * 		return the score of the specified grid
	 * @throws ArgumentInvalideException
	 */
	int getScore(Game game, Grid grid) throws ArgumentInvalideException;

	/**
	 * 		end of the game
	 * @param game
	 * @throws ArgumentInvalideException
	 */
	void endTheGame(Game game) throws ArgumentInvalideException;

}
